<script setup lang="ts">
import { message } from 'ant-design-vue'
import { computed, reactive, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import type { Host, Repo, generateRepoSetTaskParams } from '@/api'
import { api } from '@/api'
import type { DistributionParams } from '@/api/paths/types'
import { useClusterStore } from '@/store'

interface Form {
  task_name: string
  description: string
  cluster_id: string | undefined
  repo_id: string | undefined
}
const props = withDefaults(
  defineProps<{
    hostList?: Host[]
    repoList: Repo[]
  }>(),
  {
    hostList: () => [],
  },
)
const emit = defineEmits(['close', 'success', 'cancel'])

const { t } = useI18n()
const { permissions } = storeToRefs(useClusterStore())

const formRef = ref()
const form = reactive<Form>({
  description: '',
  task_name: t('vul.task.repoSetTask'),
  cluster_id: undefined,
  repo_id: undefined,
})

interface Cluster {
  cluster_id: string
  cluster_name: string
}

const tableData = ref<Host[]>([])

const clustersOptions = computed<Cluster[]>(() => permissions.value.map(i => ({ cluster_id: i.cluster_id, cluster_name: i.cluster_name })))

const repoOptions = computed(() =>
  props.repoList.filter(repo => repo.cluster_id === form.cluster_id),
)

const tableColumn = [
  {
    dataIndex: 'host_name',
    title: t('assests.hostName'),
  },
  {
    dataIndex: 'cluster_name',
    title: t('assests.cluster'),
  },
  {
    dataIndex: 'host_ip',
    title: 'IP',
  },
]

const tableState = reactive<{ selectedRowKeys: string[] }>({
  selectedRowKeys: [],
})

function onSelectChange(selectedRowKeys: string[]) {
  tableState.selectedRowKeys = selectedRowKeys
}

async function setTableData() {
  if (props.hostList.length !== 0) {
    tableData.value = props.hostList.filter(i => i.cluster_id === form.cluster_id)
  }
  else {
    const [, res] = await api.getCveHosts({ filter: { cluster_list: [form.cluster_id!] } })
    if (res)
      tableData.value = res.result
  }
  tableState.selectedRowKeys = tableData.value.map(({ host_id }) => {
    return host_id
  })
  const subStr = tableData.value.map(({ host_name }) => host_name).join(',').slice(0, 37)
  form.description = `${t('vul.task.sentence.repoDesc', { count: tableData.value.length, str: subStr })}`
}

function handleClusterChange() {
  form.repo_id = undefined
  setTableData()
}
const isExecuting = ref(false)
const isGenerating = ref(false)
async function handleCreateTask(execute: boolean = false) {
  /**
   * parse execute param for executing task
   */
  const parseExecuteParams = (
    origin: Record<string, { data: { task_id: string }, label: string }>,
  ) => {
    const params: Record<string, { task_id: string }> = {}
    Object.keys(origin).forEach((key) => {
      params[key] = {
        task_id: origin[key].data.task_id,
      }
    })
    return params
  }

  if (tableState.selectedRowKeys.length === 0) {
    message.info(t('vul.task.message.atLeastOneRepo'))
    return
  }
  try {
    execute ? (isExecuting.value = true) : (isGenerating.value = true)
    await formRef.value.validate()
    const params: DistributionParams<generateRepoSetTaskParams> = {}
    const { cluster_id, task_name, description, repo_id } = form
    params[cluster_id!] = {
      task_name,
      description,
      repo_id: repo_id!,
      host_list: tableState.selectedRowKeys,
    }
    const [_, res] = await api.generateRepoSetTask(params)

    if (res && res[cluster_id!].label === 'Succeed') {
      if (execute) {
        const params = parseExecuteParams(res)
        const [_, execRes] = await api.executeTask(params)
        if (execRes && execRes[cluster_id!].label === 'Succeed') {
          message.success(t('common.executeSuccess'))
          emit('success')
        }
        else if (execRes) {
          message.error(execRes[cluster_id!].label)
        }
        else {
          message.error(t('common.fail'))
        }
      }
      else {
        message.success(t('common.createSuccess'))
        emit('success')
      }
    }
    else if (res) {
      message.error(res[cluster_id!].label)
    }
    else {
      message.error(t('common.createFail'))
    }
  }
  catch (error) {
    console.error(new Error(error as any))
  }
  finally {
    isExecuting.value = false
    isGenerating.value = false
  }
}
</script>

<template>
  <div class="repo-task">
    <a-form ref="formRef" :model="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 18 }">
      <a-form-item :label="$t('vul.task.taskType')">
        <span>{{ $t('vul.repoSet') }}</span>
      </a-form-item>

      <a-form-item
        name="task_name"
        :label="$t('vul.task.taskName')"
        :rules="[
          { required: true, message: $t('vul.task.placeHolder.taskName') },
          { max: 20, message: $t('common.validateMsg.noMoreThanCharacters', { count: 20 }) }
        ]"
      >
        <a-input v-model:value="form.task_name" :placeholder="$t('vul.task.placeHolder.taskName')"/>
      </a-form-item>

      <a-form-item
        name="description"
        :label="t('vul.task.taskDesc')"
        :rules="[{ required: true, message: $t('vul.task.placeHolder.desc') }]"
      >
        <a-textarea v-model:value="form.description" :rows="4" :placeholder="$t('vul.task.placeHolder.desc')" :maxlength="50" />
      </a-form-item>

      <a-form-item
        name="cluster_id"
        :label="t('vul.cluster')"
        :rules="[{ required: true, message: $t('assests.placeHolder.cluster') }]"
      >
        <a-select
          v-model:value="form.cluster_id"
          :placeholder="$t('assests.placeHolder.cluster')"
          @change="handleClusterChange"
        >
          <template v-for="cluster in clustersOptions" :key="cluster.cluster_id">
            <a-select-option :value="cluster.cluster_id">
              {{ cluster.cluster_name }}
            </a-select-option>
          </template>
        </a-select>
      </a-form-item>

      <a-form-item
        v-if="form.cluster_id"
        name="repo_id"
        :label="$t('vul.task.selectRepo')"
        :rules="[{ required: true, message: $t('vul.task.placeHolder.repo') }]"
      >
        <a-select v-model:value="form.repo_id" :placeholder="$t('vul.task.placeHolder.repo')">
          <template v-for="repo in repoOptions" :key="repo.repo_id">
            <a-select-option :value="repo.repo_id">
              {{ repo.repo_name }}
            </a-select-option>
          </template>
        </a-select>
      </a-form-item>
    </a-form>

    <a-table
      row-key="host_id"
      :columns="tableColumn"
      :data-source="tableData"
      :pagination="false"
      :row-selection="{
        selectedRowKeys: tableState.selectedRowKeys,
        onChange: onSelectChange,
      }"
    />

    <a-row class="button-group" type="flex" justify="end">
      <a-space>
        <a-button @click="$emit('cancel')">
          {{ $t('common.cancel') }}
        </a-button>
        <a-button type="primary" :disabled="isExecuting" :loading="isGenerating" @click="handleCreateTask(false)">
          {{ $t('common.create') }}
        </a-button>
        <a-button type="primary" :disabled="isGenerating" :loading="isExecuting" @click="handleCreateTask(true)">
          {{ $t('common.executeImmediately') }}
        </a-button>
      </a-space>
    </a-row>
  </div>
</template>

<style scoped>
.repo-task {
  padding-bottom: 40px;
}
.button-group {
  position: absolute;
  bottom: 0;
  width: 94%;
  padding: 10px 0;
  background-color: var(--bg-drawer);
}
</style>
